Avastage useRef'i võimsus Reactis. Uurige mitmekesiseid kasutusjuhte, sealhulgas otsejuurdepääsu DOM-ile, muutuvate väärtuste säilitamist ja funktsionaalsete komponentide käitumise optimeerimist.
React useRef: Muutuvate väärtuste salvestamise mustrite valdamine
useRef on võimas hook Reactis, mis võimaldab väärtusi säilitada renderduste vahel, põhjustamata uuesti renderdamist, kui need väärtused muutuvad. Seda seostatakse sageli otse DOM-elementidele juurdepääsuga, kuid selle võimekused ulatuvad sellest palju kaugemale. See põhjalik juhend süveneb useRef'i mitmekesistesse kasutusjuhtudesse, andes teile võimaluse kirjutada tõhusamat ja hooldatavamat Reacti koodi.
useRef'i mõistmine: rohkem kui lihtsalt DOM-ile juurdepääs
Oma olemuselt tagastab useRef muudetava ref-objekti, mille .current omadus on initsialiseeritud antud argumendiga (initialValue). Tagastatud objekt püsib kogu komponendi eluea jooksul. Oluline on see, et .current omaduse muutmine ei käivita uuesti renderdamist. See on peamine erinevus useRef'i ja useState'i vahel.
Kuigi DOM-elementidele juurdepääs on levinud kasutusjuht, paistab useRef silma mis tahes muutuva väärtuse haldamisel, mille uuendamine ei pea uuesti renderdamist põhjustama. See muudab selle hindamatuks ülesannete jaoks nagu:
- Eelmiste prop'i või oleku väärtuste salvestamine.
- Loendurite või taimerite haldamine.
- Fookuse oleku jälgimine ilma uuesti renderdamist põhjustamata.
- Mis tahes muutuva väärtuse salvestamine, mis peab renderduste vahel püsima.
Põhikasutus: DOM-elementidele juurdepääs
Kõige tuntum kasutusjuht on otse DOM-elementidele juurdepääs. See on kasulik stsenaariumides, kus peate DOM-sõlmega imperatiivselt suhtlema, näiteks sisestusvälja fookustamine, selle mõõtmete mõõtmine või animatsioonide käivitamine.
Näide: sisestusvälja fookustamine
Siin on, kuidas saate kasutada useRef'i sisestusvälja fookustamiseks komponendi paigaldamisel:
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const inputRef = useRef(null);
useEffect(() => {
// Fookusta sisestusväli paigaldamisel
if (inputRef.current) {
inputRef.current.focus();
}
}, []); // Tühi sõltuvuste massiiv tagab, et see käivitub ainult üks kord paigaldamisel
return (
<input type="text" ref={inputRef} placeholder="Sisesta tekst" />
);
}
export default MyComponent;
Selgitus:
- Loome ref'i kasutades
useRef(null). Algväärtus onnull, kuna sisestuselementi pole veel olemas, kui komponent esialgu renderdatakse. - Kinnitame ref'i sisestuselemendi külge, kasutades
refprop'i:ref={inputRef}. React seabinputRef.currentautomaatselt DOM-sõlmele, kui sisestuselement on paigaldatud. - Kasutame
useEffect'i tühja sõltuvuste massiiviga ([]), et tagada efekti käivitumine ainult üks kord pärast komponendi paigaldamist. - Efekti sees kontrollime, kas
inputRef.currenton olemas (et vältida vigu, kui element pole veel saadaval) ja seejärel kutsume väljainputRef.current.focus(), et sisestusvälja fookustada.
Peale DOM-ile juurdepääsu: muutuvate väärtuste haldamine
useRef'i tegelik võimsus seisneb selle võimes salvestada muutuvaid väärtusi, mis püsivad renderduste vahel ilma uuesti renderdamist käivitamata. See avab laia valiku võimalusi komponendi käitumise optimeerimiseks ja oleku haldamiseks funktsionaalsetes komponentides.
Näide: eelmiste prop'i või oleku väärtuste salvestamine
Mõnikord on vaja pääseda juurde prop'i või olekumuutuja eelmisele väärtusele. useRef pakub puhta viisi selle tegemiseks ilma tarbetuid uuesti renderdamisi käivitamata.
import React, { useRef, useEffect } from 'react';
function MyComponent({ value }) {
const previousValue = useRef(value);
useEffect(() => {
// Uuenda ref'i .current omadust praeguse väärtusega
previousValue.current = value;
}, [value]); // Efekt käivitub iga kord, kui 'value' prop muutub
// Nüüd saate eelmisele väärtusele juurde pääseda, kasutades previousValue.current
return (
<div>
Praegune väärtus: {value}
<br />
Eelmine väärtus: {previousValue.current}
</div>
);
}
export default MyComponent;
Selgitus:
- Initsialiseerime ref'i
previousValuevalueprop'i algväärtusega. - Kasutame
useEffect'i, et uuendadapreviousValue.currentomadust iga kord, kuivalueprop muutub. - Komponendi sees saame nüüd juurde pääseda
valueprop'i eelmisele väärtusele, kasutadespreviousValue.current.
Kasutusjuhtumi näide: API vastuste muudatuste jälgimine (rahvusvaheline stsenaarium)
Kujutage ette, et ehitate armatuurlauda, mis kuvab API-st hangitud valuutakursse. API võib tagastada kursid erinevates vormingutes või erineva täpsusastmega sõltuvalt andmeallikast (nt Euroopa Keskpanga API vs Kagu-Aasia finantsasutuse API). Saate kasutada useRef'i eelmise vahetuskursi jälgimiseks ja visuaalse indikaatori kuvamiseks (nt roheline nool üles või punane nool alla), et näidata, kas kurss on pärast viimast uuendust tõusnud või langenud. See on ülioluline rahvusvahelistele kasutajatele, kes tuginevad nendele kurssidele finantsotsuste tegemisel.
Näide: loendurite või taimerite haldamine
useRef sobib suurepäraselt loendurite või taimerite haldamiseks, mis ei pea uuesti renderdamisi käivitama. Näiteks võite seda kasutada nupule vajutamise kordade arvu jälgimiseks või lihtsa taimeri rakendamiseks.
import React, { useRef, useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const clickCount = useRef(0); // Initsialiseeri ref väärtusega 0
const handleClick = () => {
clickCount.current++; // Suurenda ref'i .current omadust
setCount(clickCount.current); //Suurenda olekut, mis põhjustab uuesti renderdamise.
};
return (
<div>
<p>Nupule vajutatud: {count} korda</p>
<button onClick={handleClick}>Vajuta siia</button>
</div>
);
}
export default MyComponent;
Selgitus:
- Initsialiseerime ref'i
clickCountväärtusega 0. - Funktsioonis
handleClicksuurendameclickCount.currentomadust. See ei käivita uuesti renderdamist. - Uuendame ka olekut 'count', mis käivitab uuesti renderdamise.
Näide: Debounce-funktsiooni rakendamine
Debouncing on tehnika, mida kasutatakse funktsiooni täitmise sageduse piiramiseks. Seda kasutatakse tavaliselt otsingusisestusväljades, et vältida liigseid API-kutseid kasutaja tippimise ajal. useRef'i saab kasutada debounce-funktsioonis kasutatava taimeri ID salvestamiseks.
import React, { useState, useRef, useEffect } from 'react';
function MyComponent() {
const [searchTerm, setSearchTerm] = useState('');
const [results, setResults] = useState([]);
const timerRef = useRef(null); // Salvesta taimeri ID
const handleChange = (event) => {
const newSearchTerm = event.target.value;
setSearchTerm(newSearchTerm);
// TĂĽhjenda eelmine taimer, kui see on olemas
if (timerRef.current) {
clearTimeout(timerRef.current);
}
// Määra uus taimer
timerRef.current = setTimeout(() => {
// Simuleeri API-kutset
fetch(`https://api.example.com/search?q=${newSearchTerm}`)
.then(response => response.json())
.then(data => setResults(data.results));
}, 300); // Viivitus 300 millisekundit
};
return (
<div>
<input
type="text"
placeholder="Otsi..."
value={searchTerm}
onChange={handleChange}
/>
<ul>
{results.map(result => (
<li key={result.id}>{result.name}</li>
))}
</ul>
</div>
);
}
export default MyComponent;
Selgitus:
- Kasutame
useRef'i taimeri ID salvestamisekstimerRef'i. - Funktsioonis
handleChangetühjendame eelmise taimeri (kui see on olemas), kasutadesclearTimeout(timerRef.current). - Seejärel seame uue taimeri, kasutades
setTimeout, ja salvestame taimeri IDtimerRef.current'i. - API-kutse tehakse alles siis, kui kasutaja on 300 millisekundit tippimise lõpetanud.
Rahvusvahelistumise kaalutlused: Kui rakendate viivitusega funktsiooni (debouncing) API-kõnedega, mis kuvavad teavet eri keeltes, veenduge, et teie API toetaks rahvusvahelistumist ja tagastaks andmed kasutaja eelistatud keeles. Kaaluge Accept-Language päise kasutamist oma API-päringutes.
Näide: fookuse oleku jälgimine ilma uuesti renderdamiseta
Saate kasutada useRef'i, et jälgida, kas elemendil on fookus, ilma uuesti renderdamisi põhjustamata. See võib olla kasulik elementide stiilimiseks nende fookuse oleku alusel või kohandatud fookuse haldamise loogika rakendamiseks.
import React, { useRef, useState } from 'react';
function MyComponent() {
const [isFocused, setIsFocused] = useState(false);
const inputRef = useRef(null);
const handleFocus = () => {
setIsFocused(true);
};
const handleBlur = () => {
setIsFocused(false);
};
return (
<div>
<input
type="text"
ref={inputRef}
onFocus={handleFocus}
onBlur={handleBlur}
/>
<p>Sisend on fookuses: {isFocused ? 'Jah' : 'Ei'}</p>
</div>
);
}
export default MyComponent;
useRef vs. useState: õige tööriista valimine
Tööks õige tööriista valimiseks on oluline mõista useRef'i ja useState'i peamisi erinevusi.
| Omadus | useRef | useState |
|---|---|---|
| Käivitab uuesti renderdamise | Ei | Jah |
| Eesmärk | Muutuvate väärtuste salvestamine, mis ei pea uuesti renderdamist käivitama. DOM-elementidele juurdepääs. | Oleku haldamine, mis peab uuesti renderdamist käivitama. |
| Püsivus | Püsib renderduste vahel. | Püsib renderduste vahel, kuid väärtust uuendatakse setteri funktsiooni abil. |
Parimad tavad ja levinumad lõksud
- Ärge muutke olekut otse: Kuigi
useReflubab teil väärtusi otse muuta, vältigeuseState'iga hallatavate olekumuutujate otse muutmist. Kasutage oleku uuendamiseks alatiuseState'i pakutavat setteri funktsiooni. - Olge teadlik kõrvalmõjudest: Kui kasutate
useRef'i kasutajaliidest mõjutavate väärtuste haldamiseks, olge teadlik võimalikest kõrvalmõjudest. Veenduge, et teie kood käituks ettearvatavalt ja ei tekitaks ootamatuid vigu. - Ärge toetuge
useRef'ile renderdusloogikas: KunauseRef'i muudatused ei käivita uuesti renderdamist, ärge toetuge selle väärtustele otse, et otsustada, mida tuleks renderdada. KasutageuseState'i väärtuste jaoks, mis peavad renderdusloogikat juhtima. - Kaaluge jõudluse mõjusid: Kuigi
useRefaitab optimeerida jõudlust, vältides tarbetuid uuesti renderdamisi, olge teadlik, et muutuvate väärtuste liigne kasutamine võib muuta teie koodi raskemini mõistetavaks ja silutavaks.
Täpsemad kasutusjuhud ja mustrid
Väärtuste säilitamine komponentide eksemplaride vahel
Kuigi `useRef` säilitab väärtused *ühe* komponendi eksemplari renderduste vahel, on mõnikord vaja, et väärtus püsiks sama komponendi *erinevate* eksemplaride vahel. See nõuab veidi teistsugust lähenemist, kasutades sageli mooduli tasemel muutujat koos `useRef`-iga.
// myComponent.js
let globalCounter = 0; // Mooduli tasemel muutuja
import React, { useRef, useEffect } from 'react';
function MyComponent() {
const counterRef = useRef(globalCounter); // Initsialiseeri globaalse väärtusega
useEffect(() => {
// Uuenda globaalset loendurit iga kord, kui ref muutub
globalCounter = counterRef.current;
}, [counterRef.current]);
const increment = () => {
counterRef.current++;
//setState'i pole vaja, seega uuesti renderdamist ei toimu
};
return (
<div>
<p>Loendur: {counterRef.current}</p>
<button onClick={increment}>Suurenda</button>
</div>
);
}
export default MyComponent;
Olulised kaalutlused: See muster toob sisse globaalse muutuja, seega olge eriti ettevaatlik võimalike kõrvalmõjude ja võistlustingimuste (race conditions) suhtes, eriti keerukates rakendustes. Kaaluge alternatiivseid lähenemisviise, näiteks kontekstipakkuja (context provider) kasutamist, kui väärtust on vaja jagada mitme komponendi vahel kontrollitumal viisil.
Kokkuvõte: useRef'i võimsuse vallandamine
useRef on mitmekülgne tööriist Reactis, mis ulatub palju kaugemale lihtsalt DOM-elementidele juurdepääsust. Mõistes selle võimet salvestada muutuvaid väärtusi ilma uuesti renderdamisi käivitamata, saate optimeerida oma komponente, hallata olekut tõhusamalt ja ehitada jõudlusvõimelisemaid ja hooldatavamaid Reacti rakendusi. Pidage meeles, et kasutage seda läbimõeldult ja kaaluge alati võimalikke kompromisse jõudluse ja koodi selguse vahel.
Selles juhendis kirjeldatud mustrite valdamisega olete hästi varustatud, et kasutada useRef'i täit potentsiaali oma Reacti projektides, olgu tegemist siis lihtsa veebirakenduse või keeruka ettevõttesüsteemi ehitamisega. Ärge unustage globaalsele publikule ehitades arvestada rahvusvahelistumise ja ligipääsetavusega!